﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;

namespace Nirvana
{
    /// <summary>
    /// 配合EffectControl、particleSystem组件，预览对应效果
    /// </summary>
    [ExecuteInEditMode]
    public class PreviewObject : MonoBehaviour
    {
        private GameObject root;
        private bool m_simulateInEditMode= true;
        public bool SimulateInEditMode { get { return m_simulateInEditMode; } set { m_simulateInEditMode = value; } }
        private float frameTime;
        private double timeSinceStartup = -1.0f;


        private void Awake()
        {
            base.hideFlags = HideFlags.DontSave;
#if UNITY_EDITOR
            EditorApplication.playModeStateChanged += this.OnDispose;
#endif
        }

        private void OnEnable()
        {
            if (Application.isPlaying)
            {
                return;
            }
#if UNITY_EDITOR
            EditorApplication.update += this.OnUpdate;
            this.timeSinceStartup = EditorApplication.timeSinceStartup;
#endif


            if (this.root != null)
            {
                this.root.SetActive(true);
            }
        }
        private void OnDisable()
        {
            if (Application.isPlaying)
            {
                return;
            }
#if UNITY_EDITOR
            EditorApplication.update -= this.OnUpdate;
#endif

            if (this.root != null)
            {
                this.root.SetActive(false);
            }
        }

        private void OnDestroy()
        {
            if (this.root != null)
            {
                UnityEngine.Object.DestroyImmediate(this.root);
                this.root = null;
            }
        }

#if UNITY_EDITOR
        private void OnDispose(PlayModeStateChange state )
        {

            if (

                     (EditorApplication.isPlaying
                || EditorApplication.isPlayingOrWillChangePlaymode
                || EditorApplication.isCompiling) &&


                this.root != null)
            {
                UnityEngine.Object.DestroyImmediate(this.root);
                this.root = null;
            }
        }
#endif
        private void OnUpdate()
        {
#if UNITY_EDITOR



            if (!this.m_simulateInEditMode) return;
            double curTimeDiff = EditorApplication.timeSinceStartup - this.timeSinceStartup;
            this.timeSinceStartup = EditorApplication.timeSinceStartup;
            this.frameTime += (float)curTimeDiff;
            if (this.root == null) return;
            EffectControl effCtl = this.root.GetComponent<EffectControl>();
            if (effCtl != null)
            {
                effCtl.SimulateDelta(this.frameTime,(float)curTimeDiff);
            }
            else
            {
                float maxDuration = 0f;
                ParticleSystem[] ps = this.root.GetComponentsInChildren<ParticleSystem>();
                foreach (ParticleSystem p in ps)
                {
                    if (maxDuration < p.main.duration)
                    {
                        maxDuration = p.main.duration;
                    }
                }
                foreach (ParticleSystem p in ps)
                {
                    p.Simulate(maxDuration, false, false);
                }
            }
#endif
        }

        public void ClearPreview()
        {
#if UNITY_EDITOR
            if (this.root != null)
            {
                EditorApplication.delayCall += ()=> {
                    UnityEngine.Object.DestroyImmediate(this.root);
                    this.root = null;
                };
            }
#endif
        }

        public void SetPreview(GameObject previewObj)
        {
#if UNITY_EDITOR
            if (this.root != null)
            {
                EditorApplication.delayCall += () => {
                    UnityEngine.Object.DestroyImmediate(this.root);
                    this.root = null;
                };
            }
            this.root = previewObj;
            this.root.tag = "EditorOnly";
            this.root.transform.SetParent(base.transform, false);

            if (m_simulateInEditMode)
            {
                EffectControl effCtl = this.root.GetComponent<EffectControl>();
                if (effCtl != null)
                {
                    effCtl.SimulateInit();
                    effCtl.SimulateStart();
                }else
                {
                    ParticleSystem[] ps = this.root.GetComponentsInChildren<ParticleSystem>();
                    foreach (ParticleSystem p in ps)
                    {
                        p.Simulate(0f, false, true);
                    }
                }
            }

            this.FindAllChilde(this.root, HideFlags.DontSave);
#endif
        }

        private void FindAllChilde(GameObject root, HideFlags flag)
        {
            root.hideFlags = flag;
            for (int i = 0; i < root.transform.childCount; i++)
            {
                Transform child = root.transform.GetChild(i);
                this.FindAllChilde(child.gameObject, flag);
            }
        }

    }
}


